import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;


// 修改 ChessPanel 实现自定义观察者接口
class ChessPanel extends JPanel implements ChessObserver {
    public static final int MARGIN = 30; // 四周保留30像素的边距
    private int[][] chessGrid;
    private int boardSize;

    public ChessPanel(ChessController controller) {
        // 修改为使用自定义主题接口方法
        this.boardSize = controller.getBoardSize();
        this.chessGrid = controller.getChessGrid();
        addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent e) {
                // 检查回合
                if (!controller.checkTurn()) {
                    JOptionPane.showMessageDialog(ChessPanel.this, "请等待对方落子！");
                    return;
                }

                int boardSize = controller.getBoardSize();
                int panelWidth = getWidth();
                int panelHeight = getHeight();
                int cellSize = Math.min(
                        (panelWidth - 2 * MARGIN) / boardSize,
                        (panelHeight - 2 * MARGIN) / boardSize
                );
                int startX = (panelWidth - (boardSize - 1) * cellSize) / 2;
                int startY = (panelHeight - (boardSize - 1) * cellSize) / 2;

                int x = Math.round((e.getX() - startX) / (float)cellSize);
                int y = Math.round((e.getY() - startY) / (float)cellSize);

                if (x >= 0 && x < boardSize && y >= 0 && y < boardSize) {
                    // 检查落子范围
                    controller.moveChess(x, y);
                    controller.sendMove(x, y); // 发送落子信息
                }
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawBoard(g);     // 画棋盘
        drawChess(g);   // 画棋子
    }

    private void drawBoard(Graphics g) {
        int panelWidth = getWidth();
        int panelHeight = getHeight();
        int cellSize = Math.min(
                (panelWidth - 2 * MARGIN) / boardSize,
                (panelHeight - 2 * MARGIN) / boardSize
        );
        // 计算棋盘起始坐标（居中显示）
        int startX = (panelWidth - (boardSize - 1) * cellSize) / 2;
        int startY = (panelHeight - (boardSize - 1) * cellSize) / 2;

        for (int i = 0; i < boardSize; i++) {
            int x = startX + i * cellSize;
            int y = startY + i * cellSize;
            // 垂直方向线
            g.drawLine(x, startY, x, startY + (boardSize - 1) * cellSize);
            // 水平方向线
            g.drawLine(startX, y, startX + (boardSize - 1) * cellSize, y);
        }
    }

    private void drawChess(Graphics g) {
        int panelWidth = getWidth();
        int panelHeight = getHeight();
        int cellSize = Math.min(
                (panelWidth - 2 * MARGIN) / boardSize,
                (panelHeight - 2 * MARGIN) / boardSize
        );
        int startX = (panelWidth - (boardSize - 1) * cellSize) / 2;
        int startY = (panelHeight - (boardSize - 1) * cellSize) / 2;
        for (int i = 0; i < boardSize; i++) {
            for (int j = 0; j < boardSize; j++) {
                if (chessGrid[i][j] != 0) {
                    int chessX = startX + i * cellSize - 10; // 调整棋子位置
                    int chessY = startY + j * cellSize - 10;
                    g.setColor(chessGrid[i][j] == 1 ? Color.BLACK : Color.RED);
                    g.fillOval(chessX, chessY, 20, 20);
                }
            }
        }
    }

    @Override
    public void updateBoard(int[][] chessGrid, int x, int y, int player, boolean isGameOver) {
        this.chessGrid = chessGrid;
        repaint();
        if (isGameOver) {
            String message = "玩家 " + player + " 胜利！";
            JOptionPane.showMessageDialog(this, message, "游戏结束", JOptionPane.INFORMATION_MESSAGE);
        }
    }
}

public class ChessGameAndPanel extends JFrame {
    private final ChessPanel chessPanel;
    private final ChessController chessController;

    public ChessGameAndPanel(ChessController chessController) {
        chessPanel = new ChessPanel(chessController);
        this.chessController = chessController;
        this.chessController.addObserver(chessPanel); // 添加面板观察者


        // 创建顶部按钮面板（使用 FlowLayout）
        JPanel buttonPanel = new JPanel();
        JButton restartBtn = new JButton("重新开始");
        JButton undoBtn = new JButton("悔棋");
        JButton saveBtn = new JButton("存档");
        JButton loadBtn = new JButton("读档");
        JButton networkBtn = new JButton("网络对战");
        buttonPanel.add(restartBtn);
        buttonPanel.add(undoBtn);
        buttonPanel.add(saveBtn);
        buttonPanel.add(loadBtn);
        buttonPanel.add(networkBtn);

        // 按钮事件绑定
        restartBtn.addActionListener((ActionEvent _) -> {
            chessController.resetGame();
            chessPanel.repaint();
        });
        undoBtn.addActionListener((ActionEvent _) -> {
            if (chessController.undoMove())
                chessPanel.repaint();
            else {
                JOptionPane.showMessageDialog(this, "无法悔棋！");
            }
        });
        saveBtn.addActionListener((ActionEvent _) -> {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileFilter(new FileNameExtensionFilter("五子棋存档文件", "gobang"));
            int result = fileChooser.showSaveDialog(this);
            if (result == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();
                if (!file.getName().endsWith(".gobang")) {
                    file = new File(file.getParentFile(), file.getName() + ".gobang");
                }
                // GameSaveManager.saveGame(chessBoard, file.getAbsolutePath());
                chessController.saveGame(file.getAbsolutePath());
                JOptionPane.showMessageDialog(this, "存档成功！");
            }
        });
        loadBtn.addActionListener((ActionEvent _) -> {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileFilter(new FileNameExtensionFilter("五子棋存档文件", "gobang"));
            int result = fileChooser.showOpenDialog(this);
            if (result == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();
                // GameSaveManager.loadGame(chessBoard, file.getAbsolutePath());
                chessController.loadGame(file.getAbsolutePath());
                chessPanel.repaint();
                JOptionPane.showMessageDialog(this, "读档成功！");
            }
        });
        
        networkBtn.addActionListener((ActionEvent _) -> {
            Object[] options = {"创建房间", "加入房间"};
            int choice = JOptionPane.showOptionDialog(this, 
                "选择网络对战模式", 
                "网络对战", 
                JOptionPane.YES_NO_OPTION, 
                JOptionPane.QUESTION_MESSAGE, 
                null, options, options[0]);
                
            if (choice == 0) {
                // 创建房间
                String portStr = JOptionPane.showInputDialog(this, "输入端口号:", "12345");
                try {
                    int port = Integer.parseInt(portStr);
                    chessController.enbleNetworking(true);
                    chessController.startServer(port);
                    JOptionPane.showMessageDialog(this, "房间创建成功，等待对手连接...");
                    if (chessController.waitForClient() != null) {
                        JOptionPane.showMessageDialog(this, "对手已连接!");
                    }
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, "创建房间失败: " + ex.getMessage());
                    System.out.println("创建房间失败: " + ex.getMessage());
                }
            } else if (choice == 1) {
                // 加入房间
                String host = JOptionPane.showInputDialog(this, "输入服务器IP:", "localhost");
                String portStr = JOptionPane.showInputDialog(this, "输入端口号:", "12345");
                try {
                    int port = Integer.parseInt(portStr);
                    chessController.enbleNetworking(true);
                    chessController.connectToServer(host, port);
                    JOptionPane.showMessageDialog(this, "成功连接到房间!");
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(this, "连接失败: " + ex.getMessage());
                    System.out.println("连接失败: " + ex.getMessage());
                }
            }
        });

        // 设置窗口主布局为 BorderLayout
        setLayout(new BorderLayout());
        add(buttonPanel, BorderLayout.NORTH); // 按钮在顶部
        add(chessPanel, BorderLayout.CENTER); // 棋盘居中并自动拉伸

        setTitle("五子棋");
        setSize(600, 600);
        setMinimumSize(new Dimension(600, 600));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBackground(new Color(255, 206, 158)); // 木质色调背景
        setVisible(true);
    }
}